#ifndef FILTER_PATTERN_H
#define FILTER_PATTERN_H

#include <string>
#include <vector>

using namespace std;

class Person
{
public:
    ~Person() {}
    Person(string name, string gender, string maritalStatus);

    string getName();
    string getGender();
    string getMaritalStatus();

private:
    string name, gender, maritalStatus;
};

class Criteria
{
public:
    ~Criteria() {}

    virtual vector<Person*> meetCriteria(vector<Person*> persons) = 0;
};

class CriteriaMale : public Criteria
{
public:
    ~CriteriaMale() {}

    vector<Person*> meetCriteria(vector<Person*> persons) override;
};

class CriteriaFemale : public Criteria
{
public:
    ~CriteriaFemale() {}

    vector<Person*> meetCriteria(vector<Person*> persons) override;
};

class CriteriaSingle : public Criteria
{
public:
    ~CriteriaSingle() {}

    vector<Person*> meetCriteria(vector<Person*> persons) override;
};

class AndCriteria : public Criteria
{
public:
    AndCriteria(Criteria* criteria, Criteria* otherCriteria);
    ~AndCriteria() {}

    vector<Person*> meetCriteria(vector<Person*> persons) override;

private:
    Criteria* criteria;
    Criteria* otherCriteria;
};

class OrCriteria : public Criteria
{
public:
    OrCriteria(Criteria* criteria, Criteria* otherCriteria);
    ~OrCriteria() {}

    vector<Person*> meetCriteria(vector<Person*> persons) override;

private:
    Criteria* criteria;
    Criteria* otherCriteria;
};

#endif // FILTER_PATTERN_H

/*
    vector<Person*> persons;

    persons.push_back(new Person("Robert","Male", "Single"));
    persons.push_back(new Person("John","Male", "Married"));
    persons.push_back(new Person("Laura","Female", "Married"));
    persons.push_back(new Person("Diana","Female", "Single"));
    persons.push_back(new Person("Mike","Male", "Single"));
    persons.push_back(new Person("Bobby","Male", "Single"));

    Criteria* male = new CriteriaMale();
    Criteria* female = new CriteriaFemale();
    Criteria* single = new CriteriaSingle();
    Criteria* singleMale = new AndCriteria(single, male);
    Criteria* singleOrFemale = new OrCriteria(single, female);

    cout << "Males : " << endl;
    printPersons(male->meetCriteria(persons));

    cout << "\nFemales : " << endl;
    printPersons(female->meetCriteria(persons));

    cout << "\nSingle Males : " << endl;
    printPersons(singleMale->meetCriteria(persons));

    cout << "\nSingle Or Females" << endl;
    printPersons(singleOrFemale->meetCriteria(persons));


    void printPersons(vector<Person*> persons)
    {
        vector<Person*>::iterator it = persons.begin();
        for(; it < persons.end(); it++)
        {
            cout << "Person : [ Name : " << (*it)->getName() << ", Gender : " << (*it)->getGender() << ", Marital Status : " << (*it)->getMaritalStatus() << " ]" << endl;
        }
    }
    */
